package club.itstudio.IContainer.service;

import club.itstudio.IContainer.entity.CourseExperiment;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashSet;
import java.util.List;

@Service
public class CourseExperimentService {
    private JdbcTemplate jdbcTemplate;
    private Logger logger = LoggerFactory.getLogger(this.getClass());
    private CourseExperimentMapper courseExperimentMapper = new CourseExperimentMapper();

    @Autowired
    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    public boolean insert(CourseExperiment courseExperiment) {
        String sql = "insert into course_experiment(experiment_name, description, course_id, " +
                "image_id, container_alive_time, memory_limit, cpu_share_limit, cpu_set_limit, " +
                "end_time, network_name, subnet) " +
                "values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
        try {
            return jdbcTemplate.update(sql, courseExperiment.experimentName, courseExperiment.description,
                    courseExperiment.courseID, courseExperiment.imageID, courseExperiment.containerAliveTime,
                    courseExperiment.memoryLimit, courseExperiment.cpuShareLimit, courseExperiment.cpuSetLimit,
                    courseExperiment.endTime, courseExperiment.networkName, courseExperiment.subnet) == 1;
        }catch (DataAccessException e) {
            logger.info("error insert new experiment:", e);
            return false;
        }
    }

    public CourseExperiment getByID(int id) {
        String sql = "select * from course_experiment where id=?";
        CourseExperiment courseExperiment = null;
        try {
            courseExperiment = jdbcTemplate.queryForObject(sql, courseExperimentMapper, id);
        }catch (DataAccessException e) {
            logger.info("error get course experiment by id:" + id, e);
        }
        return courseExperiment;
    }

    public List<CourseExperiment> getByCourseID(int courseID) {
        String sql = "select * from course_experiment where course_id=?";
        return jdbcTemplate.query(sql, courseExperimentMapper, courseID);
    }

    public boolean delete(int id) {
        String sql = "delete from course_experiment where id=?";
        try {
            return jdbcTemplate.update(sql, id) == 1;
        }catch (DataAccessException e) {
            logger.info("error delete course experiment by id:" + id, e);
            return false;
        }
    }

    public boolean deleteByCourseID(int courseID) {
        String sql = "delete from course_experiment where course_id=?";
        try {
            jdbcTemplate.update(sql, courseID);
            return true;
        }catch (DataAccessException e) {
            logger.info("error delete course experiment by course id:" + courseID, e);
            return false;
        }
    }

    private List<CourseExperiment> getAll() {
        String sql = "select * from course_experiment";
        return jdbcTemplate.query(sql, courseExperimentMapper);
    }

    // 子网分配
    public String subnetAllocate() {
        List<CourseExperiment> experiments = getAll();
        HashSet<String> subnetSet = new HashSet<>();
        for (CourseExperiment experiment : experiments) {
            subnetSet.add(experiment.subnet);
        }

        for (int i = 2; i < 255; i++) {
            String subnet = String.format("192.168.%d.1/24", i);
            if (!subnetSet.contains(subnet)) {
                return subnet;
            }
        }
        return "";
    }
}

class CourseExperimentMapper implements RowMapper<CourseExperiment> {
    @Override
    public CourseExperiment mapRow(ResultSet resultSet, int i) throws SQLException {
        CourseExperiment courseExperiment = new CourseExperiment();
        courseExperiment.id = resultSet.getInt("id");
        courseExperiment.experimentName = resultSet.getString("experiment_name");
        courseExperiment.description = resultSet.getString("description");
        courseExperiment.courseID = resultSet.getInt("course_id");
        courseExperiment.imageID = resultSet.getInt("image_id");
        courseExperiment.containerAliveTime = resultSet.getInt("container_alive_time");
        courseExperiment.memoryLimit = resultSet.getInt("memory_limit");
        courseExperiment.cpuShareLimit = resultSet.getInt("cpu_share_limit");
        courseExperiment.cpuSetLimit = resultSet.getInt("cpu_set_limit");
        courseExperiment.endTime = resultSet.getLong("end_time");
        courseExperiment.networkName = resultSet.getString("network_name");
        courseExperiment.subnet = resultSet.getString("subnet");
        return courseExperiment;
    }
}